#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <unistd.h>
#include <cstdlib>
#include <sys/wait.h>
#include <string.h>



class ctrlpipe
{
public:
    ctrlpipe()
    {}
    ~ctrlpipe()
    {}

    
    void _writr(int wfd, int cnt)
    {
        
        std::string put = "hellow pipe 我是一个子进程：" + std::to_string(getpid()) + ","+ std::to_string(cnt);
        sleep(1);
        ssize_t n = write(wfd, put.c_str(), put.size());
        if (n < 0)
        {
            perror("write error");
        }   
    }

    bool _read(int rfd)
    {
        char _buf[1024];
        _buf[0] = 0;
        ssize_t n = read(rfd, _buf, sizeof(_buf) - 1);
        if(n > 0)
        {
            _buf[n] = '\0'; // 手动添加结束符
            std::cout << _buf << std::endl;
            return true;
        }
        else if(n == 0)
        {
            std::cout << "子进程关闭写端，父进程结束" << std::endl;
            return false;
        }
        else
        {
            perror("read error");
            return false;
        }
    }
};


// 验证管道中的4种极端情况


// 写端不关，写端不写 -- 管道里没有数据，进程会被阻塞
// 读端不关，读端不读 -- 管道被写满了，不会写
// 写端不写，写端关闭 -- 读端会读到，返回值为0，表示到了文件末尾
// 读端关闭，写正常   -- 操作系统会杀死写进程


void child_write(int wfd, ctrlpipe& pipe)
{
    int cnt = 10;
    while(cnt--)
    {
        pipe._writr(wfd, cnt);
    }
}

void father_read(int rfd, ctrlpipe& pipe)
{
     
    while(true)
    {
        if(pipe._read(rfd))
        {
            ;
        }
    }

}




int main()
{
    // 创建管道
    // 创建匿名管道，内存级文件，没有文件名，没有inode，等

    int pipefd[2] = {0};
    int n = pipe(pipefd);
    if(n < 0)
    {
        std::cerr << "pipe error" << std::endl;
    }

    // std::cout << "pipefd[0]: " << pipefd[0] << std::endl;
    // std::cout << "pipefd[1]: " << pipefd[1] << std::endl;

    // 父子进程
    ctrlpipe ctrl;

    pid_t id = fork();

    if(id == 0) // 子写
    {
        close(pipefd[0]);
        child_write(pipefd[1], ctrl);

        close(pipefd[1]);
        exit(0);
    }
    else if(id > 0) // 父读
    {
        close(pipefd[1]);
        father_read(pipefd[0], ctrl);
        
        int status = 0;
        pid_t result = waitpid(id, &status, 0);
        close(pipefd[0]);
        std::cout << "子进程退出状态: " << WEXITSTATUS(status) << std::endl;
    }
    
    return 0;
}

